home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / ROM_Kernel_Manuals / Devices / dev_examples / Console.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-20  |  11.9 KB  |  369 lines

  1. /*
  2.  * Console.c
  3.  *
  4.  * Example of opening a window and using the console device
  5.  * to send text and control sequences to it.  The example can be
  6.  * easily modified to do additional control sequences.
  7.  *
  8.  * Compile with SAS C 5.10: LC -b1 -cfistq -v -y -L
  9.  *
  10.  * Run from CLI only.
  11.  */
  12.  
  13. #include <exec/types.h>
  14. #include <exec/io.h>
  15. #include <exec/memory.h>
  16. #include <intuition/intuition.h>
  17. #include <libraries/dos.h>
  18. #include <devices/console.h>
  19.  
  20. #include <clib/exec_protos.h>
  21. #include <clib/alib_protos.h>
  22. #include <clib/dos_protos.h>
  23. #include <clib/intuition_protos.h>
  24.  
  25. #include <stdio.h>
  26.  
  27. #ifdef LATTICE
  28. int CXBRK(void) { return(0); }     /* Disable Lattice CTRL/C handling */
  29. int chkabort(void) { return(0); }  /* really */
  30. #endif
  31.  
  32.  
  33. /* Note - using two character <CSI> ESC[.  Hex 9B could be used instead */
  34. #define RESETCON  "\033c"
  35. #define CURSOFF   "\033[0 p"
  36. #define CURSON    "\033[ p"
  37. #define DELCHAR   "\033[P"
  38.  
  39. * SGR (set graphic rendition) */
  40. #define COLOR02   "\033[32m"
  41. #define COLOR03   "\033[33m"
  42. #define ITALICS   "\033[3m"
  43. #define BOLD      "\033[1m"
  44. #define UNDERLINE "\033[4m"
  45. #define NORMAL    "\033[0m"
  46.  
  47.  
  48. /* our functions */
  49. void cleanexit(UBYTE *,LONG);
  50. void cleanup(void);
  51. BYTE OpenConsole(struct IOStdReq *,struct IOStdReq *, struct Window *);
  52. void CloseConsole(struct IOStdReq *);
  53. void QueueRead(struct IOStdReq *, UBYTE *);
  54. UBYTE ConGetChar(struct MsgPort *, UBYTE *);
  55. LONG ConMayGetChar(struct MsgPort *, UBYTE *);
  56. void ConPuts(struct IOStdReq *, UBYTE *);
  57. void ConWrite(struct IOStdReq *, UBYTE *, LONG);
  58. void ConPutChar(struct IOStdReq *, UBYTE);
  59. void main(int argc, char **argv);
  60. struct NewWindow nw =
  61.     {
  62.     10, 10,                           /* starting position (left,top) */
  63.     620,180,                          /* width, height */
  64.     -1,-1,                            /* detailpen, blockpen */
  65.     CLOSEWINDOW,                      /* flags for idcmp */
  66.     WINDOWDEPTH|WINDOWSIZING|
  67.     WINDOWDRAG|WINDOWCLOSE|
  68.     SMART_REFRESH|ACTIVATE,           /* window flags */
  69.     NULL,                             /* no user gadgets */
  70.     NULL,                             /* no user checkmark */
  71.     "Console Test",                   /* title */
  72.     NULL,                             /* pointer to window screen */
  73.     NULL,                             /* pointer to super bitmap */
  74.     100,45,                           /* min width, height */
  75.     640,200,                          /* max width, height */
  76.     WBENCHSCREEN                      /* open on workbench screen */
  77.     };
  78.  
  79.  
  80. /* Opens/allocations we'll need to clean up */
  81. struct Library  *IntuitionBase = NULL;
  82. struct Window   *win = NULL;
  83. struct IOStdReq *writeReq = NULL;    /* IORequest block pointer */
  84. struct MsgPort  *writePort = NULL;   /* replyport for writes      */
  85. struct IOStdReq *readReq = NULL;     /* IORequest block pointer */
  86. struct MsgPort  *readPort = NULL;    /* replyport for reads       */
  87. BOOL OpenedConsole = FALSE;
  88.  
  89. BOOL FromWb;
  90.  
  91. void main(argc, argv)
  92. int argc;
  93. char **argv;
  94.     {
  95.     struct IntuiMessage *winmsg;
  96.     ULONG signals, conreadsig, windowsig;
  97.     LONG lch;
  98.     SHORT InControl = 0;
  99.     BOOL Done = FALSE;
  100.     UBYTE ch, ibuf;
  101.     UBYTE obuf[200];
  102.     BYTE error;
  103.  
  104.     FromWb = (argc==0L) ? TRUE : FALSE;
  105.  
  106.     if(!(IntuitionBase=OpenLibrary("intuition.library",0)))
  107.          cleanexit("Can't open intuition\n",RETURN_FAIL);
  108.  
  109.     /* Create reply port and io block for writing to console */
  110.     if(!(writePort = CreatePort("RKM.console.write",0)))
  111.          cleanexit("Can't create write port\n",RETURN_FAIL);
  112.  
  113.     if(!(writeReq = (struct IOStdReq *)
  114.                     CreateExtIO(writePort,(LONG)sizeof(struct IOStdReq))))
  115.          cleanexit("Can't create write request\n",RETURN_FAIL);
  116.  
  117.     /* Create reply port and io block for reading from console */
  118.     if(!(readPort = CreatePort("RKM.console.read",0)))
  119.          cleanexit("Can't create read port\n",RETURN_FAIL);
  120.  
  121.     if(!(readReq = (struct IOStdReq *)
  122.                    CreateExtIO(readPort,(LONG)sizeof(struct IOStdReq))))
  123.          cleanexit("Can't create read request\n",RETURN_FAIL);
  124.  
  125.     /* Open a window */
  126.     if(!(win = OpenWindow(&nw)))
  127.          cleanexit("Can't open window\n",RETURN_FAIL);
  128.  
  129.     /* Now, attach a console to the window */
  130.     if(error = OpenConsole(writeReq,readReq,win))
  131.          cleanexit("Can't open console.device\n",RETURN_FAIL);
  132.     else OpenedConsole = TRUE;
  133.  
  134.     /* Demonstrate some console escape sequences */
  135.     ConPuts(writeReq,"Here's some normal text\n");
  136.     sprintf(obuf,"%s%sHere's text in color 3 & italics\n",COLOR03,ITALICS);
  137.     ConPuts(writeReq,obuf);
  138.     ConPuts(writeReq,NORMAL);
  139.     Delay(50);      /* Delay for dramatic demo effect */
  140.     ConPuts(writeReq,"We will now delete this asterisk =*=");
  141.     Delay(50);
  142.     ConPuts(writeReq,"\b\b");  /* backspace twice */
  143.     Delay(50);
  144.     ConPuts(writeReq,DELCHAR); /* delete the character */
  145.     Delay(50);
  146.  
  147.     QueueRead(readReq,&ibuf); /* send the first console read request */
  148.  
  149.     ConPuts(writeReq,"\n\nNow reading console\n");
  150.     ConPuts(writeReq,"Type some keys.  Close window when done.\n\n");
  151.  
  152.     conreadsig = 1 << readPort->mp_SigBit;
  153.     windowsig = 1 << win->UserPort->mp_SigBit;
  154.  
  155.     while(!Done)
  156.         {
  157.         /* A character, or an IDCMP msg, or both could wake us up */
  158.         signals = Wait(conreadsig|windowsig);
  159.  
  160.         /* If a console signal was received, get the character */
  161.         if (signals & conreadsig)
  162.             {
  163.             if((lch = ConMayGetChar(readPort,&ibuf)) != -1)
  164.                 {
  165.                 ch = lch;
  166.                 /* Show hex and ascii (if printable) for char we got.
  167.                  * If you want to parse received control sequences, such as
  168.                  * function or Help keys,you would buffer control sequences
  169.                  * as you receive them, starting to buffer whenever you
  170.                  * receive 0x9B (or 0x1B[ for user-typed sequences) and
  171.                  * ending when you receive a valid terminating character
  172.                  * for the type of control sequence you are receiving.
  173.                  * For CSI sequences, valid terminating characters
  174.                  * are generally 0x40 through 0x7E.
  175.                  * In our example, InControl has the following values:
  176.                  * 0 = no, 1 = have 0x1B, 2 = have 0x9B OR 0x1B and [,
  177.                  * 3 = now inside control sequence, -1 = normal end esc,
  178.                  * -2 = non-CSI(no [) 0x1B end esc
  179.                  * NOTE - a more complex parser is required to recognize
  180.                  *  other types of control sequences.
  181.                  */
  182.  
  183.                 /* 0x1B ESC not followed by '[', is not CSI seq */
  184.                 if (InControl==1)
  185.                     {
  186.                     if(ch=='[') InControl = 2;
  187.                     else InControl = -2;
  188.                     }
  189.  
  190.                 if ((ch==0x9B)||(ch==0x1B))  /* Control seq starting */
  191.                     {
  192.                     InControl = (ch==0x1B) ? 1 : 2;
  193.                     ConPuts(writeReq,"=== Control Seq ===\n");
  194.                     }
  195.  
  196.                 /* We'll show value of this char we received */
  197.                 if (((ch >= 0x1F)&&(ch <= 0x7E))||(ch >= 0xA0))
  198.                    sprintf(obuf,"Received: hex %02x = %c\n",ch,ch);
  199.                 else sprintf(obuf,"Received: hex %02x\n",ch);
  200.                 ConPuts(writeReq,obuf);
  201.  
  202.                 /* Valid ESC sequence terminator ends an ESC seq */
  203.                 if ((InControl==3)&&((ch >= 0x40) && (ch <= 0x7E)))
  204.                     {
  205.                     InControl = -1;
  206.                     }
  207.                 if (InControl==2) InControl = 3;
  208.                 /* ESC sequence finished (-1 if OK, -2 if bogus) */
  209.                 if (InControl < 0)
  210.                     {
  211.                     InControl = 0;
  212.                     ConPuts(writeReq,"=== End Control ===\n");
  213.                     }
  214.                 }
  215.             }
  216.  
  217.         /* If IDCMP messages received, handle them */
  218.         if (signals & windowsig)
  219.             {
  220.             /* We have to ReplyMsg these when done with them */
  221.             while (winmsg = (struct IntuiMessage *)GetMsg(win->UserPort))
  222.                 {
  223.                 switch(winmsg->Class)
  224.                     {
  225.                     case CLOSEWINDOW:
  226.                       Done = TRUE;
  227.                       break;
  228.                     default:
  229.                       break;
  230.                      }
  231.                 ReplyMsg((struct Message *)winmsg);
  232.                 }
  233.             }
  234.         }
  235.  
  236.     /* We always have an outstanding queued read request
  237.      * so we must abort it if it hasn't completed,
  238.      * and we must remove it.
  239.      */
  240.     if(!(CheckIO(readReq)))  AbortIO(readReq);
  241.     WaitIO(readReq);     /* clear it from our replyport */
  242.  
  243.     cleanup();
  244.     exit(RETURN_OK);
  245.     }
  246.  
  247. void cleanexit(UBYTE *s,LONG n)
  248.     {
  249.     if(*s & (!FromWb)) printf(s);
  250.     cleanup();
  251.     exit(n);
  252.     }
  253.  
  254. void cleanup()
  255.     {
  256.     if(OpenedConsole) CloseConsole(writeReq);
  257.     if(readReq)       DeleteExtIO(readReq);
  258.     if(readPort)      DeletePort(readPort);
  259.     if(writeReq)      DeleteExtIO(writeReq);
  260.     if(writePort)     DeletePort(writePort);
  261.     if(win)           CloseWindow(win);
  262.     if(IntuitionBase) CloseLibrary(IntuitionBase);
  263.     }
  264.  
  265.  
  266. /* Attach console device to an open Intuition window.
  267.  * This function returns a value of 0 if the console
  268.  * device opened correctly and a nonzero value (the error
  269.  * returned from OpenDevice) if there was an error.
  270.  */
  271. BYTE OpenConsole(writereq, readreq, window)
  272. struct IOStdReq *writereq;
  273. struct IOStdReq *readreq;
  274. struct Window *window;
  275.     {
  276.     BYTE error;
  277.  
  278.     writereq->io_Data = (APTR) window;
  279.     writereq->io_Length = sizeof(struct Window);
  280.     error = OpenDevice("console.device", 0, writereq, 0);
  281.     readreq->io_Device = writereq->io_Device; /* clone required parts */
  282.     readreq->io_Unit   = writereq->io_Unit;
  283.     return(error);
  284.     }
  285.  
  286. void CloseConsole(struct IOStdReq *writereq)
  287.     {
  288.     CloseDevice(writereq);
  289.     }
  290.  
  291. /* Output a single character to a specified console
  292.  */
  293. void ConPutChar(struct IOStdReq *writereq, UBYTE character)
  294.     {
  295.     writereq->io_Command = CMD_WRITE;
  296.     writereq->io_Data = (APTR)&character;
  297.     writereq->io_Length = 1;
  298.     DoIO(writereq);
  299.     /* command works because DoIO blocks until command is done
  300.      * (otherwise ptr to the character could become invalid)
  301.      */
  302.     }
  303.  
  304.  
  305. /* Output a stream of known length to a console
  306.  */
  307. void ConWrite(struct IOStdReq *writereq, UBYTE *string, LONG length)
  308.     {
  309.     writereq->io_Command = CMD_WRITE;
  310.     writereq->io_Data = (APTR)string;
  311.     writereq->io_Length = length;
  312.     DoIO(writereq);
  313.     /* command works because DoIO blocks until command is done
  314.      * (otherwise ptr to string could become invalid in the meantime)
  315.      */
  316.     }
  317.  
  318.  
  319. /* Output a NULL-terminated string of characters to a console
  320.  */
  321. void ConPuts(struct IOStdReq *writereq,UBYTE *string)
  322.     {
  323.     writereq->io_Command = CMD_WRITE;
  324.     writereq->io_Data = (APTR)string;
  325.     writereq->io_Length = -1;  /* means print till terminating null */
  326.     DoIO(writereq);
  327.     }
  328.  
  329. /* Queue up a read request to console, passing it pointer
  330.  * to a buffer into which it can read the character
  331.  */
  332. void QueueRead(struct IOStdReq *readreq, UBYTE *whereto)
  333.    {
  334.    readreq->io_Command = CMD_READ;
  335.    readreq->io_Data = (APTR)whereto;
  336.    readreq->io_Length = 1;
  337.    SendIO(readreq);
  338.    }
  339.  
  340.  
  341. /* Check if a character has been received.
  342.  * If none, return -1
  343.  */
  344. LONG ConMayGetChar(struct MsgPort *msgport, UBYTE *whereto)
  345.     {
  346.     register temp;
  347.     struct IOStdReq *readreq;
  348.  
  349.     if (!(readreq = (struct IOStdReq *)GetMsg(msgport))) return(-1);
  350.     temp = *whereto;                /* get the character */
  351.     QueueRead(readreq,whereto);     /* then re-use the request block */
  352.     return(temp);
  353.     }
  354.  
  355. /* Wait for a character
  356.  */
  357. UBYTE ConGetChar(struct MsgPort *msgport, UBYTE *whereto)
  358.     {
  359.     register temp;
  360.     struct IOStdReq *readreq;
  361.  
  362.     WaitPort(msgport);
  363.     readreq = (struct IOStdReq *)GetMsg(msgport);
  364.     temp = *whereto;               /* get the character */
  365.     QueueRead(readreq,whereto);    /* then re-use the request block*/
  366.     return((UBYTE)temp);
  367.     }
  368.  
  369.